package com.victor.controller.pay;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.victor.entity.Mybybookcoupon;
import com.victor.entity.Picturebook;
import com.victor.entity.Recharge;
import com.victor.entity.Seriesandpicbook;
import com.victor.pay.alipay.AlipayConfig;
import com.victor.pay.app.PayCommonUtil;
import com.victor.pay.app.UtilDate;
import com.victor.pay.app.XMLUtil4jdom;
import com.victor.pay.wxpay.WxPayConfig;
import com.victor.service.BookcaseService;
import com.victor.service.BybookcouponService;
import com.victor.service.PicturebookService;
import com.victor.service.RechargeService;
import com.victor.service.SeriesandpicbookService;
import com.victor.utils.Msg;

@RestController
public class PayController {

	@Autowired
	private RechargeService rechargeService;

	@Autowired
	private SeriesandpicbookService spService;

	@Autowired
	private PicturebookService picService;

	@Autowired
	private BybookcouponService couponService;

	@Autowired
	private BookcaseService bookService;

	@SuppressWarnings("unchecked")
	@RequestMapping("/apppay")
	@ResponseBody
	public Msg pay(Recharge recharge) {
		String orderno = UtilDate.getOrderNum();
		recharge.setOrdernumber(orderno);
		if (rechargeService.add(recharge) == true) {
			switch (recharge.getPayment()) {
			case 1:
				// 支付宝支付
				AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
						AlipayConfig.private_key, AlipayConfig.FORMAT, AlipayConfig.input_charset,
						AlipayConfig.ali_public_key, AlipayConfig.sign_type);
				// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
				AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
				// SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
				AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
				model.setSubject("支付"); // 商品名称
				model.setOutTradeNo(orderno); // 商户订单号(自动生成)
				model.setTotalAmount(String.valueOf(recharge.getMoney())); // 支付金额
				model.setProductCode("QUICK_MSECURITY_PAY"); // 销售产品码
				model.setSellerId(AlipayConfig.partner); // 商家id
				model.setBody("alipay");
				model.setTimeoutExpress("60m"); // 超时关闭该订单时间
				ali_request.setBizModel(model);
				ali_request.setNotifyUrl(AlipayConfig.notify_url); // 回调地址
				AlipayTradeAppPayResponse responses = null;
				try {
					responses = client.sdkExecute(ali_request);
				} catch (AlipayApiException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				String orderStr = responses.getBody();
				return Msg.success().add("url", orderStr);
			case 2:
				// 微信支付
				SortedMap<Object, Object> sArray = new TreeMap<Object, Object>();
				Map<Object, Object> map = new HashMap<Object, Object>();
				sArray.put("appid", WxPayConfig.appid);
				sArray.put("mch_id", WxPayConfig.mch_id);
				sArray.put("fee_type", "CNY");
				sArray.put("device_info", WxPayConfig.device_info);
				sArray.put("body", "wxpay");
				String noncestr = PayCommonUtil.CreateNoncestr();
				sArray.put("nonce_str", noncestr);
				sArray.put("out_trade_no", orderno);
				BigDecimal b = new BigDecimal(recharge.getMoney());
				BigDecimal r = b.multiply(new BigDecimal("100"));
				String s = r.toString();
				if (s.indexOf(".") > 0) {
					s = s.replaceAll("0+?$", "");// 去掉后面无用的零
					s = s.replaceAll("[.]$", "");// 如小数点后面全是零则去掉小数点
				}
				sArray.put("total_fee", s);
				sArray.put("notify_url", WxPayConfig.notify_url);
				sArray.put("trade_type", "APP");
				sArray.put("sign_type", "MD5");

				// 设置签名
				String sign = PayCommonUtil.createSign("UTF-8", sArray);
				sArray.put("sign", sign);
				// 封装请求参数结束
				String requestXML = PayCommonUtil.getRequestXml(sArray);
				// 调用统一下单接口
				String result = PayCommonUtil.httpsRequest(WxPayConfig.service, "POST", requestXML);
				Map<Object, Object> parameterMap2 = new TreeMap<Object, Object>();
				try {
					/**
					 * 统一下单接口返回正常的prepay_id，再按签名规范重新生成签名后，将数据传输给APP。参与签名的字段名为appId，partnerId，prepayId，nonceStr，timeStamp，package。注意：package的值格式为Sign=WXPay
					 **/
					Map<String, String> parameterMap1 = XMLUtil4jdom.doXMLParse(result);
					parameterMap2.put("appid", WxPayConfig.appid);
					parameterMap2.put("partnerid", WxPayConfig.mch_id);
					String prepayid = parameterMap1.get("prepay_id");
					parameterMap2.put("prepayid", prepayid);
					parameterMap2.put("package", "Sign=WXPay");
					parameterMap2.put("noncestr", parameterMap1.get("nonce_str"));
					// 本来生成的时间戳是13位，但是ios必须是10位，所以截取了一下
					/*
					 * String timestamp=String.valueOf(System.currentTimeMillis() /
					 * 1000).toString();
					 */
					String timestamp = Long
							.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10)) + "";
					parameterMap2.put("timestamp", timestamp);
					String sign2 = PayCommonUtil.createSign("utf-8", parameterMap2);
					parameterMap2.put("sign", sign2);
				} catch (JDOMException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				return Msg.success().add("url", parameterMap2);
			default:
				break;
			}
		}
		return null;
	}

	/**
	 * 获取购买系列所需金额
	 * 
	 * @param sid
	 * @return
	 */
	@GetMapping("getSeriesMoney/{sid}")
	public Msg getSeriesMoney(@PathVariable("sid") Integer sid) {
		List<Seriesandpicbook> pictureidList = spService.findBySid(sid);
		List<String> pidList = new ArrayList<>();
		pictureidList.stream().forEach(c -> pidList.add(String.valueOf(c.getSpPid())));
		BigDecimal reduce = new BigDecimal("0");
		if (pidList != null && !pidList.isEmpty()) {
			List<Picturebook> batchFindByIds = picService.batchFindByIds(pidList);
			reduce = batchFindByIds.stream().map(c -> BigDecimal.valueOf(Double.valueOf(c.getPPrice())))
					.reduce(BigDecimal.ZERO, BigDecimal::add);
		} else {
			return Msg.fail("无效商品");
		}
		return Msg.success().add("price", reduce.toString());
	}

	/**
	 * 支付 - 生成订单
	 * @param recharge
	 * @return
	 */
	@PostMapping("/pay")
	public Msg pay2(Recharge recharge) {
		Mybybookcoupon mycoupon = couponService.findById(recharge.getCouponid());
		List<Seriesandpicbook> pictureidList = spService.findBySid(Integer.valueOf(recharge.getSid()));
		if(pictureidList ==null || pictureidList.isEmpty()) {
			return Msg.fail("无效商品");
		}
		boolean bool = bookService.contrastBySid(recharge.getSid(), recharge.getUserid());
		if (!bool) {
			return Msg.fail("该商品已经购买");
		}
		Map<String, Object> map = new HashMap<>();
		// 生成流水号
		String orderno = UtilDate.getOrderNum();
		recharge.setOrdernumber(orderno);
		if (mycoupon != null && mycoupon.getBybookcoupon() != null) {
			map.put("orderno", orderno);
			// 计算实际支付金额
			double zprice = Double.valueOf(recharge.getMoney());
			double coupon = Double.valueOf(mycoupon.getBybookcoupon().getMoney());
			double sjprice = zprice - coupon;
			recharge.setActualMoney(String.format("%.2f", sjprice));
			map.put("price", String.format("%.2f", sjprice));
			bool = rechargeService.add(recharge);
			if (bool) {
				return Msg.success().result(map);
			}
		} else {
			map.put("orderno", orderno);
			map.put("price", recharge.getMoney());
			recharge.setActualMoney(recharge.getMoney());
			bool = rechargeService.add(recharge);
			if (bool) {
				return Msg.success().result(map);
			}
		}
		return null;
	}

}
